"""
Author        yongfa
Date          2022-07-11 14:48:29
LastEditTime  2023-07-24 14:59:30
LastEditors   yongfa
Description   业务处理
"""

from flask import current_app, g
from sqlalchemy import or_
from flask_jwt_extended import create_access_token, create_refresh_token, get_jwt_identity, verify_jwt_in_request

from app.extensions import redis_client

from app.extensions.services import BaseService, SimpleService
from app.extensions.sqlalchemy import model_list_to_dict
from app.extensions.utils.enums import LoginTypeEnum
from app.extensions.utils import token_key
from app.extensions.exception import Success, Failed, TokenLogoutException, TokenRefreshException
from app.extensions.utils.validator import validate_columns, validate_password
from app.modules.v1.permission.models import Role, Menu, Apis
from app.modules.v1.dict_data.models import Dict, DictType


def judge_super_admin(role: object) -> None:
    """判断是否是超级管理员

    Args:
        role (object): 角色对象

    Raises:
        Failed: 错误信息
    """
    if role.is_super_admin:
        raise Failed(message='违规操作')


class UserServices(BaseService):

    def create(self):
        """创建"""
        data = validate_columns(self.model, self.args)
        if not data:
            return Failed(message='请求参数不能为空！')
        password = self.args.get('password')
        validate_password(password)
        data['password'] = password
        if self.conditions:
            data.update(self.conditions)

        item = self.model(**data)
        role_id = data.get('role_id')
        if role_id:
            role = Role.get(id=role_id)
            judge_super_admin(role)
            item.role = role

        role_ids = self.args.get('role_ids', [])
        if role_ids:
            roles = Role.query.filter(Role.id.in_(role_ids), Role.is_super_admin.is_(False)).all()
            item.roles = roles
        item.save()
        return Success()

    def update(self, id):
        """更新"""
        data = validate_columns(self.model, self.args)
        conditions = {'id': id}
        if self.conditions:
            conditions.update(self.conditions)

        item = self.model.get_or_404(**conditions)
        for role in item.roles:
            judge_super_admin(role)

        # 密码
        password = self.args.get('password')
        if password:
            validate_password(password)
            item.password = password
        # 多角色
        role_ids = self.args.get('role_ids')
        if role_ids:
            roles = Role.query.filter(Role.id.in_(role_ids), Role.is_super_admin.is_(False)).all()
            item.roles = roles
        item.update(**data)
        return Success()

    def soft_delete(self, id):
        """软删除"""
        conditions = {'id': id}
        if self.conditions:
            conditions.update(self.conditions)
        item = self.model.get_or_404(**conditions)
        for role in item.roles:
            judge_super_admin(role)
        item.soft_delete()
        return Success()


class UserInfoServices(SimpleService):

    def user_info(self):
        """用户信息"""
        user = self.model.get_or_404(id=g.user_id)
        data = user.to_dict()
        return Success(result=data)

    def permissions(self):
        user = self.model.get_or_404(id=g.user_id)

        data = {}
        output_fields = ['id', 'value', 'label', 'name', 'path', 'method', 'icon']
        result = {}
        attrs = ["apis", 'menus']
        is_super_admin = False
        for role in user.roles:
            if role.is_super_admin:
                is_super_admin = True
                break

            result = role.get_all_permissions(result, attrs, role)

        if is_super_admin:
            data['menus'] = model_list_to_dict(Menu.get_all(),
                                               output_fields=output_fields,
                                               #    exclude_fields=exclude_fields
                                               )
            data['apis'] = model_list_to_dict(Apis.get_all(),
                                              output_fields=output_fields,
                                              #   exclude_fields=exclude_fields
                                              )
        else:
            for attr in attrs:
                data[attr] = model_list_to_dict(result.get(attr), output_fields=output_fields)

        return Success(result=data)

    def user_edit(self):
        """编辑用户"""
        user = self.model.get_or_404(id=g.user_id)
        data = validate_columns(self.model, self.args)
        if not data:
            return Failed(message='请求参数不能为空！')
        user.update(**data)
        return Success(user)

    def user_password(self):
        """修改密码"""
        old_password = self.args.get('old_password')
        password = self.args.get('new_password')
        validate_password(password)
        user = self.model.get_or_404(id=g.user_id)
        if user and user.verify_password(old_password):
            user.password = password
            user.save()
            key = token_key(user.id)
            redis_client.delete(key)
            return Success()
        else:
            return Failed(message='旧密码不正确')


class UserLoginServices(SimpleService):
    """Description:    用户验证， 支持手机号，用户名，邮箱登录"""

    def login(self):
        """登录"""
        username = self.args.get('username')
        password = self.args.get('password')
        login_type = self.args.get('login_type')
        auth = self.args.get('auth')

        queryset = self.model.query.filter(
            self.model.username == username,
            self.model.delete_time == current_app.config.get('DEFAULT_DELETE_TIME')  # 默认删除时间
        )

        if auth is not None:
            queryset = queryset.filter(self.model.auth == auth)

        if login_type == LoginTypeEnum.PASSWORD.value:

            user = queryset.first()
            if user is None:
                return Failed(message='用户不存在')
            if user and password and user.verify_password(password):
                token = user.get_user_token()
                return Success(result=token, message='登录成功')
            return Failed(message='用户名或密码错误')
        else:
            raise Failed(message='暂时不支持该登录方式')

    def refresh(self):
        """刷新token"""
        token = self.model().get_refresh_token()
        return Success(result=token, message='刷新成功')

    def logout(self):
        """退出登录"""
        key = token_key(g.user_id)
        redis_client.delete(key)
        return Success(result=None, message='退出成功')
